package progress.exa30_2;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;

public class ObjectAnalyzer{

    private ArrayList<Object> visited = new ArrayList<>();

    /**
     * 此方法利用放射将传入的对象toString化
     * @param obj
     * @return String
     */
    public String toString(Object obj){
        //首先判断传入的对象是否空对象，如果是直接返回null
        if (obj == null) return "null";
        //然后判断是否已经传入过相同的对象进来，如果是，返回 ...
        if (visited.contains(obj)) return "...";
        //将obj对象加入全局变量visited中
        visited.add(obj);
        //获得传入对象的class实例
        Class<?> cl = obj.getClass();
        //判断传入的对象是否是字符串对象，如果是，强转后直接返回
        if (cl == String.class){
            return (String) obj;
        }
        //基本数据类型直接返回其对应的基本类型数值描述
//        if(cl==Integer.class||cl==Double.class||cl==Short.class||cl==Byte.class||cl==Float.class||cl==Long.class||cl==Boolean.class||cl==Character.class){
//            return obj.toString();
//        }
        //如果是数组类型，则
        if (cl.isArray()) {
            String r = cl.getComponentType() + "[]{";

            for (int i = 0; i < Array.getLength(obj); i++) {
                if (i > 0){
                    r += ",";
                }
                //获得数组指定位置的元素
                Object val = Array.get(obj, i);
                //判断元素是不是基本类型
                if (cl.getComponentType().isPrimitive()) {
                    r += val;
                } else {
                    r += toString(val);
                }
            }
            System.out.println(r);
            return r + "}";
        }

        String r = cl.getName();

        //将传入对象String化
        do {
            r += "[";
            Field[] fields = cl.getDeclaredFields();
            //这个操作可以让反射机制对私有属性也能进行操作
            AccessibleObject.setAccessible(fields, true);
            for (Field f : fields) {
                if (!Modifier.isStatic(f.getModifiers())) {
                    if (!r.endsWith("[")) r += ",";
                    r += f.getName() + "=";
                    try {
                        Class t = f.getType();
                        Object val = f.get(obj);
                        //判断属性是不是基本类型
                        if (t.isPrimitive()) {
                            r += val;
                        }
                        else r += toString(val);
                    }
                    catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            r += "]";
            //获得此类的父类型Class
            cl = cl.getSuperclass();
        } while (cl != null);

        return r;
    }
}
